package com.winning.bdu.dl.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.csvreader.CsvReader;
import com.csvreader.CsvWriter;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.nio.charset.Charset;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @Author: shipengfei
 * @Description:
 * @Date: 2019-05-24 9:49
 */
@Slf4j
public class CsvUtils {

    /**
     * 读取csv文件（默认逗号分隔，默认字符集）
     *
     * @param filename
     * @param clazz
     * @param <T>
     * @return
     * @throws IOException
     */
    public static <T> List<T> load(String filename, Class<T> clazz) throws IOException {
        List<JSONObject> jsonObjects = load(filename, ',', Charset.defaultCharset());
        // timestamp转换
        return JSON.parseArray(JSON.toJSONStringWithDateFormat(jsonObjects, "yyyy-MM-dd HH:mm:ss.SSS"), clazz);
    }

    public static List<JSONObject> load(String filename, char separator, Charset charset) throws IOException {
        CsvReader csvReader = new CsvReader(filename, separator, charset);
        // Maximum column length greater than 100,000
        csvReader.setSafetySwitch(false);
        csvReader.readHeaders();
        List<String> headers = Arrays.asList(csvReader.getHeaders());
        List<JSONObject> datas = new ArrayList<>();
        while (csvReader.readRecord()) {
            List<String> cols = new LinkedList<>();
            for (int i = 0; i < headers.size(); i++) {
                cols.add(csvReader.get(i));
            }
            datas.add(stringToJSONObject(headers, cols));
        }
        return datas;
    }

    /**
     * 单行数据->JSONObject
     *
     * @param headerCols 头行列
     * @param dataCols   数据列
     * @return JSONObject
     */
    private static JSONObject stringToJSONObject(List<String> headerCols, List<String> dataCols) {
        JSONObject jsonObject = new JSONObject(true);
        for (int i = 0; i < headerCols.size(); i++) {
            jsonObject.put(headerCols.get(i), dataCols.get(i));
        }
        return jsonObject;
    }

    /**
     * list转csv文件
     *
     * @param fileName
     * @param headers
     * @param dataRows
     */
    public static void list2Csv(String fileName, List<String> headers, List<Map<String, Object>> dataRows) throws IOException {
        list2Csv(fileName, ',', Charset.forName("UTF-8"), headers, dataRows);
    }

    /**
     * list转csv文件
     *
     * @param fileName
     * @param dataRows
     * @throws IOException
     */
    public static void list2Csv(String fileName, List<Map<String, Object>> dataRows) throws IOException {
        if (dataRows == null || dataRows.isEmpty()) {
            log.info("dataRows数据为空！");
            return;
        }
        List<String> headers = dataRows.get(0).keySet().stream().collect(Collectors.toList());
        list2Csv(fileName, ',', Charset.defaultCharset(), headers, dataRows);
    }

    /**
     * list转csv文件
     *
     * @param fileName
     * @param separator
     * @param charset
     * @param headers
     * @param dataRows
     */
    public static void list2Csv(String fileName, char separator, Charset charset,
                                List<String> headers, List<Map<String, Object>> dataRows) throws IOException {
        log.info("------------------>>>>>{}<<<<<--------------------", charset);
        CsvWriter csvWriter = new CsvWriter(fileName, separator, charset);
        try {
            csvWriter.writeRecord(headers.stream().toArray(size -> new String[size]));
            List<String[]> rows = dataRows.parallelStream().map(obj -> headers.stream()
                    .map(header -> obj.get(header) == null ? null : obj.get(header).toString()).toArray(size -> new String[size]))
                    .collect(Collectors.toList());
            Iterator<String[]> it = rows.iterator();
            while (it.hasNext()) {
                csvWriter.writeRecord(it.next());
            }
        } finally {
            csvWriter.close();
        }
    }

    /**
     * json字符串转csv文件
     *
     * @param fileName
     * @param dataStr
     * @throws IOException
     */
    public static void json2Csv(String fileName, String dataStr) throws IOException {
        List<Map<String, Object>> dataRows = JSONObject.parseObject(dataStr, List.class);
        list2Csv(fileName, dataRows);
    }

    /**
     * json字符串转csv文件
     *
     * @param fileName
     * @param headerStr
     * @param dataStr
     * @throws IOException
     */
    public static void json2Csv(String fileName, String headerStr, String dataStr) throws IOException {
        List<Map<String, Object>> dataRows = JSONObject.parseObject(dataStr, List.class);
        List<String> headers = Stream.of(headerStr.split(",")).collect(Collectors.toList());
        list2Csv(fileName, headers, dataRows);
    }

//    public static void main(String[] args) {
//        List<String> headers = new ArrayList<String>();
//        headers.add("id_a");
//        headers.add("id_b");
//        headers.add("name");
//        headers.add("subject");
//        headers.add("sex");
//        headers.add("card");
//        headers.add("column_a");
//        headers.add("column_b");
//        headers.add("column_c");
//        headers.add("column_d");
//        headers.add("column_e");
//        headers.add("column_f");
//        headers.add("column_g");
//        headers.add("column_h");
//        List<Map<String, Object>> dataRows = new ArrayList<Map<String, Object>>();
//        for (int i = 1; i <= 15000; i++) {
//            Map<String, Object> row = new HashMap<String, Object>();
//            row.put("id_a", i);
//            row.put("id_b", i + "_b");
//            row.put("name", "name" + i);
//            row.put("subject", "subject" + i);
//            row.put("sex", "男");
//            row.put("card", "adfadsfadsfadsfasdfas" + i);
//            row.put("column_a", "column_a" + i);
//            row.put("column_b", "column_b" + i);
//            row.put("column_c", "column_c" + i);
//            row.put("column_d", "column_d" + i);
//            row.put("column_e", "column_e" + i);
//            row.put("column_f", "column_f" + i);
//            row.put("column_g", "column_g" + i);
//            row.put("column_h", "column_h" + i);
//            dataRows.add(row);
//        }
//      /*  try {
//            list2Csv("F:\\2.csv", dataRows);
//        } catch (IOException e) {
//            e.printStackTrace();
//        }*/
//        try (OutputStream outputStream = new FileOutputStream("F:\\123.txt")) {
//            String str = JSONArray.toJSON(dataRows).toString();
//            byte[] bytes = str.getBytes("UTF-8");
//            outputStream.write(bytes);
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//
//  /*      String dataStr = "[{\"subject\":\"subject1\",\"name\":\"name1\",\"id\":\"1\"},{\"subject\":\"subject2\",\"name\":\"name2\",\"id\":\"2\"}]";
//        String headers = "id,name,subject,nnn,bbb";
//        try {
//            json2Csv("F:\\2.csv", headers, dataStr);
//        } catch (IOException e) {
//            e.printStackTrace();
//        }*/
//    }

}
